home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume4 / dos2coco < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  34.3 KB

  1. Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
  2. From: crds@ncoast.UUCP (Glenn A. Emelko)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i119: MSDOS <-> COCO File Utilities
  5. Keywords: MSDOS COCO DISK TRANSFER
  6. Message-ID: <12663@ncoast.UUCP>
  7. Date: 11 Oct 88 02:19:08 GMT
  8. Sender: allbery@ncoast.UUCP
  9. Reply-To: crds@ncoast.UUCP (Glenn A. Emelko)
  10. Organization: Cleveland Public Access UN*X, Cleveland, OH
  11. Lines: 1501
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. Posting-number: Volume 4, Issue 119
  15. Submitted-by: "Glenn A. Emelko" <crds@ncoast.UUCP>
  16. Archive-name: dos2coco
  17.  
  18. Based upon the response in the past week regarding my MSDOS<->COCO file
  19. utilities, I've decided to post it to the net for all to see.  It's not
  20. elegant by any means, and you'll probably find my assembler the easiest
  21. to follow of all of it, but it does all work.  I submit this for use as
  22. public domain, with the only restriction that it not be used for profit
  23. by anyone in part or in whole without first contacting myself.  This is
  24. in the true spirit of public domain, and I scoff at all of those people
  25. who post "shareware," so there.
  26.  
  27. Glenn A. Emelko
  28. crds@ncoast
  29.  
  30. snail-mail address:
  31. 305 Mentor Ave.
  32. Painesville, OH 44077
  33.  
  34. Allright, here it is... Have fun...
  35.  
  36. #!/bin/sh
  37. # This is a shell archive, meaning:
  38. # 1. Remove everything above the #!/bin/sh line.
  39. # 2. Save the resulting text in a file.
  40. # 3. Execute the file with /bin/sh (not csh) to create the files:
  41. #    dirc.asm
  42. #    dirc.c
  43. #    fromc.c
  44. #    toc.c
  45. # This archive created: Sat Oct  8 08:06:14 1988
  46. export PATH; PATH=/bin:$PATH
  47. if test -f 'dirc.asm'
  48. then
  49.     echo shar: over-writing existing file "'dirc.asm'"
  50. fi
  51. cat << \SHAR_EOF > 'dirc.asm'
  52. CSEG        SEGMENT PARA PUBLIC 'CODE'
  53.  
  54. ;---------------
  55. ;
  56. ;    DIRC.COM -- all segments set to CSEG upon entry
  57. ;
  58. ;    USAGE:
  59. ;        DIRC [filename[.ext]]<CR>
  60. ;
  61. ;        [filename[.ext]] is used to specify the file(s) whose
  62. ;            directory you want to list.
  63. ;
  64. ;        The information provided includes the free space on the disk.
  65. ;            The freespace is listed both in Granules and Bytes.
  66. ;            The display for each file includes its size in bytes,
  67. ;                the number of granules it occupies, the file
  68. ;                type, and the file mode.
  69. ;
  70. ;        You may use the global characters ? and * in the filename and
  71. ;            extention parameters.
  72. ;
  73. ;        If you do not specify a filename, it defaults to *.*
  74. ;
  75. ;        If you do not specify a filename extention, it defaults to *.
  76. ;
  77. ;
  78. ;        To assemble this program, do the following:
  79. ;
  80. ;
  81. ;        masm dirc;
  82. ;        link dirc;
  83. ;        exe2bin dirc.exe dirc.com
  84. ;        erase dirc.exe
  85. ;
  86. ;---------------
  87.         ASSUME    CS:CSEG,DS:CSEG,SS:CSEG,ES:CSEG
  88.  
  89.         ORG    100H
  90. ;---------------
  91. ;
  92. ;    ENTRY -- Link to start of program (past variables)
  93. ;
  94. ;---------------
  95. ENTRY:        JMP    START
  96. ;---------------
  97. ;
  98. ;    TEXT -- Directory listing header
  99. ;
  100. ;---------------
  101. DRIVENAME    EQU    'A'
  102.  
  103. TEXT        DB    ' Volume in drive ',DRIVENAME,' is COCO disk',13,10
  104.         DB    ' Directory of COCO disk',13,10,10,'$'
  105.  
  106. DRIVENO        EQU    DRIVENAME-'A'
  107. ;---------------
  108. ;
  109. ;    TYPETAB, TYPEn -- Types for COCO directory entries
  110. ;
  111. ;---------------
  112. TYPETAB        DW    TYPE0
  113.         DW    TYPE1
  114.         DW    TYPE2
  115.         DW    TYPE3
  116. TYPE0        DB    'BASIC    $'
  117. TYPE1        DB    'Data     $'
  118. TYPE2        DB    'Program  $'
  119. TYPE3        DB    'Text     $'
  120. ;---------------
  121. ;
  122. ;    ASCII, ASCIIn -- File modes for COCO directory entries
  123. ;
  124. ;---------------
  125. ASCII        DW    ASCII0
  126.         DW    ASCII1
  127. ASCII0        DB    'Binary$'
  128. ASCII1        DB    'ASCII$'
  129. ;---------------
  130. ;
  131. ;    NUMFILES, GRANSFREE, BYTESFREE -- Text for directory ending printout
  132. ;
  133. ;---------------
  134. NUMFILES    DB    ' File(s)$'
  135. GRANSFREE    DB    ' Grans, $'
  136. BYTESFREE    DB    ' Bytes free$'
  137. ;---------------
  138. ;
  139. ;    NUMBUF -- Expansion buffer for binary to decinal conversions
  140. ;
  141. ;---------------
  142. NUMBUF        DB    6 DUP (?)
  143. ;---------------
  144. ;
  145. ;    FCOUNT, GCOUNT -- File count and Granule count for dir info
  146. ;
  147. ;---------------
  148. FCOUNT        DW    0
  149. GCOUNT        DW    0
  150. ;---------------
  151. ;
  152. ;    FILAOK, FILOK -- For wildcarding, File always ok and this file ok
  153. ;
  154. ;---------------
  155. FILAOK        DB    0
  156. FILOK        DB    0
  157. ;---------------
  158. ;
  159. ;    GRANS, GSIZE, SECSIZE -- Number of grans on the disk, number of
  160. ;        bytes per gran, and sector size
  161. ;
  162. ;---------------
  163. GRANS        DW    68
  164. GSIZE        DW    2304
  165. SECSIZE        DW    256
  166. ;---------------
  167. ;
  168. ;    NBSEC -- Save area for MSDOS bytes per sector (changed, must restore)
  169. ;
  170. ;---------------
  171. NBSEC        DB    0
  172. ;---------------
  173. ;
  174. ;    FAT -- FAT information buffer read from COCO disk
  175. ;
  176. ;---------------
  177. FAT        DB    256 DUP (?)
  178. ;---------------
  179. ;
  180. ;    DIRBUF -- Directory sector buffer read from COCO disk
  181. ;
  182. ;---------------
  183. DIRBUF        DB    256 DUP (?)
  184. ;---------------
  185. ;
  186. ;    START -- Start of DIRC.COM
  187. ;
  188. ;---------------
  189. START:        CALL    CHECKAOK        ;Set filaok if all files are
  190.                         ;to be listed
  191.         MOV    DX,OFFSET TEXT        ;Print out directory header
  192.         MOV    AH,9
  193.         INT    21H
  194.  
  195.         XOR    AX,AX            ;Get MSDOS disk info pointer
  196.         MOV    ES,AX
  197.         LES    BX,ES:[78H]
  198.  
  199.         MOV    AL,ES:[BX+3]        ;Get MSDOS bytes per sector
  200.         MOV    NBSEC,AL        ;and save it
  201.  
  202.         MOV    BYTE PTR ES:[BX+3],1    ;Set bytes per sector to 256
  203.  
  204.         PUSH    CS            ;Restore ES to CSEG
  205.         POP    ES
  206. ;---------------
  207. ;
  208. ;    Do disk FAT read, 1 sector, buffer=FAT, track 17, sector 2, side 0
  209. ;        disk B:
  210. ;
  211. ;---------------
  212.         MOV    AX,0201H
  213.         MOV    BX,OFFSET FAT
  214.         MOV    CX,1102H
  215.         MOV    DX,DRIVENO
  216.         INT    13H
  217.  
  218.         MOV    CX,9            ;# of directory sectors
  219. ;---------------
  220. ;
  221. ;    RLOOP -- Main loop for directory read
  222. ;
  223. ;---------------
  224. RLOOP:        PUSH    CX            ;Save loop counter
  225.  
  226.         MOV    AX,12            ;Calc sector number (3-11)
  227.         SUB    AX,CX
  228.         MOV    CX,AX
  229.  
  230.         MOV    CH,17            ;Track number 17
  231.         MOV    BX,OFFSET DIRBUF    ;Buffer=DIRBUF
  232.         MOV    AX,0201H        ;Read 1 sector
  233.         MOV    DX,DRIVENO        ;Head 0, disk B:
  234.         INT    13H            ;Do BIOS read
  235.  
  236.         MOV    CX,8            ;Number of entries in sector
  237. ;---------------
  238. ;
  239. ;    PNEXT -- Secondary loop, for each file within directory sector
  240. ;
  241. ;---------------
  242. PNEXT:        MOV    AL,[BX]            ;Get entry first byte
  243.  
  244.         OR    AL,AL            ;Zero, file has been killed
  245.         JZ    NEXTENT
  246.  
  247.         CMP    AL,0FFH            ;0FFh, no more in sector
  248.         JZ    LASTENT
  249.  
  250.         CALL    CHECKFIL        ;Check if entry is ok to list
  251.                         ;result: filok=1, yes
  252.  
  253.         PUSH    CX            ;Save count and buffer pointer
  254.         PUSH    BX
  255.  
  256.         ADD    BX,11            ;Offset to file info
  257.  
  258.         CMP    FILOK,1            ;This file to be listed ?
  259.         JNZ    NODISP1            ;No, skip display
  260.  
  261.         SUB    BX,11            ;Point to file name again
  262.  
  263.         INC    FCOUNT            ;Count one more file listed
  264.  
  265.         MOV    CX,8            ;Print out file name, 1 space,
  266.         CALL    PSTRING            ;File extention, and 4 more
  267.         MOV    CX,1            ;Spaces. Adjust BX to file
  268.         CALL    SPACES            ;Info
  269.         MOV    CX,3
  270.         CALL    PSTRING
  271.         MOV    CX,4
  272.         CALL    SPACES
  273.  
  274. NODISP1:    MOV    AX,[BX+1]        ;AL=file mode, AH=first gran #
  275.         MOV    CX,[BX+3]        ;CX=# of bytes in last sector
  276.         XCHG    CH,CL            ;6809 format (HIGH, LOW)
  277.         MOV    BL,[BX]            ;BL is file type
  278.  
  279.         PUSH    AX            ;Save mode, gran, and type
  280.         PUSH    BX
  281.         CALL    CALCDISP        ;Calc file size, and display
  282.  
  283.         POP    BX            ;Restore mode, gran, and type
  284.         CMP    FILOK,1            ;File ok to use?
  285.         JNZ    NODISP2            ;No, dont display
  286.  
  287.         XOR    BH,BH            ;Find text for file type
  288.         SHL    BX,1
  289.         MOV    DX,TYPETAB[BX]
  290.  
  291.         MOV    AH,9            ;Print text
  292.         INT    21H
  293.  
  294.         POP    BX            ;BL=file mode
  295.         PUSH    BX            ;Maintain stack integrety
  296.  
  297.         XOR    BH,BH            ;Z=nonascii file type
  298.         OR    BL,BL
  299.         JZ    NONASCII
  300.  
  301.         MOV    BL,2            ;Offset for ASCII message
  302.  
  303. NONASCII:    MOV    DX,ASCII[BX]        ;Get message and print it
  304.         MOV    AH,9
  305.         INT    21H
  306.         CALL    CRLF            ;Followed by CRLF
  307.  
  308. NODISP2:    POP    AX            ;Pop stack information
  309.         POP    BX
  310.         POP    CX            ;Restore count for entries
  311.  
  312. NEXTENT:    ADD    BX,20H            ;Point to next entry
  313.         LOOP    PNEXT            ;Loop for all 8 in sector
  314.  
  315. LASTENT:    POP    CX            ;Restore outer loop count
  316.         LOOP    RLOOPX            ;Loop for all 9 sectors
  317.  
  318.         MOV    CX,3            ;Last line, print disk info
  319.         CALL    SPACES            ;3 spaces in
  320.  
  321.         MOV    AX,FCOUNT        ;Number of files
  322.         CALL    MAKENUM            ;Make numeric and print
  323.  
  324.         MOV    DX,OFFSET NUMFILES    ;Print "File(s)" message
  325.         MOV    AH,9
  326.         INT    21H
  327.  
  328.         MOV    AX,GRANS        ;Number of grans free
  329.         CALL    MAKENUM            ;Make numeric and print
  330.  
  331.         MOV    DX,OFFSET GRANSFREE    ;Print "Grans" message
  332.         MOV    AH,9
  333.         INT    21H
  334.  
  335.         MOV    AX,GRANS        ;Number of grans free
  336.         MOV    CX,2304            ;Compute bytes free
  337.         MUL    CX
  338.         CALL    MAKEBNUM        ;Make big numeric and print
  339.  
  340.         MOV    DX,OFFSET BYTESFREE    ;Print "Bytes" message
  341.         MOV    AH,9
  342.         INT    21H
  343.  
  344.         CALL    CRLF            ;Do a CRLF
  345.  
  346.         XOR    AX,AX            ;Point to MSDOS disk info
  347.         MOV    ES,AX
  348.         LES    BX,ES:[78H]
  349.  
  350.         MOV    AL,NBSEC        ;Get MSDOS bytes per sector
  351.         MOV    ES:[BX+3],AL        ;Restore to old value
  352.  
  353.         MOV    AX,4C00H        ;Exit to DOS, no errors
  354.         INT    21H
  355.  
  356. RLOOPX:        JMP    RLOOP            ;Vector for loop (too far)
  357. ;---------------
  358. ;
  359. ;    SPACES -- print CX spaces on screen
  360. ;
  361. ;---------------
  362. SPACES:        MOV    AH,2
  363.         MOV    DL,' '
  364.         INT    21H
  365.         LOOP    SPACES
  366.         RET
  367. ;---------------
  368. ;
  369. ;    PSTRING -- print string at BX with length CX, return BX=BX+CX
  370. ;
  371. ;---------------
  372. PSTRING:    MOV    DL,[BX]
  373.         INC    BX
  374.         MOV    AH,2
  375.         INT    21H
  376.         LOOP    PSTRING
  377.         RET
  378. ;---------------
  379. ;
  380. ;    CRLF -- Do CRLF to screen, dont use any registers
  381. ;
  382. ;---------------
  383. CRLF:        PUSH    AX
  384.         PUSH    DX
  385.         MOV    AH,2
  386.         MOV    DL,13
  387.         INT    21H
  388.         MOV    DL,10
  389.         INT    21H
  390.         POP    DX
  391.         POP    AX
  392.         RET
  393. ;---------------
  394. ;
  395. ;    CALCDISP -- calculate file size, and display if necessary
  396. ;
  397. ;---------------
  398. CALCDISP:    MOV    GCOUNT,0        ;File currently has no grans
  399.         JMP    CALCDISP1        ;Initialized, continue...
  400.  
  401. NEXTGRAN:    ADD    CX,GSIZE        ;Count more bytes in file
  402.  
  403. CALCDISP1:    MOV    AL,AH            ;Get gran number in AX
  404.         XOR    AH,AH
  405.  
  406.         DEC    GRANS            ;Drop gran from free space
  407.         INC    GCOUNT            ;And add gran to file size
  408.  
  409.         MOV    BX,OFFSET FAT        ;Point to FAT info
  410.         ADD    BX,AX            ;Point to GRAN entry for file
  411.  
  412.         MOV    AH,[BX]            ;Get next gran number or end
  413.         OR    AH,AH            ;Sign set, last gran in file
  414.         JNS    NEXTGRAN
  415.  
  416.         XOR    AL,AL            ;Compute number of bytes left
  417.         AND    AH,3FH            ;AH is number of sects, so
  418.         DEC    AH            ;AX is number of bytes.  Dont
  419.         JS    NOADD            ;Count last (CX had it)
  420.  
  421.         ADD    CX,AX            ;More than 1 left, add 256*AH
  422.  
  423. NOADD:        MOV    AX,CX            ;Get number of bytes in file
  424.         CMP    FILOK,1            ;Do we print this?
  425.         JNZ    NODISP3            ;No...
  426.  
  427.         CALL    MAKENUM            ;Make numeric and print
  428.  
  429.         MOV    AX,GCOUNT        ;Get gran count for file
  430.         CALL    MAKENUM            ;Make numeric and print
  431.  
  432.         MOV    CX,2            ;Print 2 spaces
  433.         CALL    SPACES
  434.  
  435. NODISP3:    RET                ;Done with calcdisp
  436. ;---------------
  437. ;
  438. ;    MAKENUM -- Make AX a decimal value, and print it to the screen
  439. ;
  440. ;---------------
  441. MAKENUM:    MOV    BX,OFFSET NUMBUF    ;NUMBUF is area for conversion
  442.  
  443.         XOR    DX,DX            ;DX:AX is number
  444.  
  445.         MOV    CX,10000        ;Initial divisor
  446.  
  447. DIVLP1:        DIV    CX            ;AX=AX/CX, DX is remainder
  448.  
  449.         ADD    AL,30H            ;Convert it to ASCII
  450.  
  451.         MOV    [BX],AL            ;And put it in buffer
  452.         INC    BX
  453.  
  454.         MOV    AX,CX            ;Divide divisor by 10
  455.         PUSH    DX            ;Save remainder
  456.         MOV    CX,10
  457.         XOR    DX,DX            ;DX:AX is divisor
  458.         DIV    CX
  459.         MOV    CX,AX            ;New divisor in CX
  460.         POP    AX            ;Old remainder in AX
  461.  
  462.         CMP    CX,1            ;Divisor=1 (done indicator)
  463.         JNZ    DIVLP1            ;No, loop for next character
  464.  
  465.         MOV    CX,4            ;# of possible leading 0's
  466. ;---------------
  467. ;
  468. ;    LZDROPCOM -- Drop leading zero's (change to spaces) for CX counts
  469. ;             Also puts last character in buffer at [BX] for callers
  470. ;
  471. ;---------------
  472. LZDROPCOM:    PUSH    CX            ;Save number of possible 0's
  473.  
  474.         ADD    AL,30H            ;Put last character in buffer
  475.         MOV    [BX],AL
  476.  
  477.         MOV    BX,OFFSET NUMBUF    ;Point to head of buffer
  478.  
  479. LZDROP:        CMP    BYTE PTR [BX],30H    ;Is this character a 0?
  480.         JNZ    DONE            ;No, finished
  481.  
  482.         MOV    BYTE PTR [BX],' '    ;Blank it
  483.         INC    BX
  484.  
  485.         LOOP    LZDROP            ;Go for CX characters
  486.  
  487. DONE:        MOV    BX,OFFSET NUMBUF    ;Print NUMBUF for CX+1 chars
  488.         POP    CX
  489.         INC    CX
  490.         CALL    PSTRING
  491.         RET
  492. ;---------------
  493. ;
  494. ;    MAKENUM -- Make DX:AX a decimal value, and print it to the screen
  495. ;           Max value is 199999
  496. ;---------------
  497. MAKEBNUM:    MOV    BX,OFFSET NUMBUF    ;Output buffer
  498.         MOV    CX,10000        ;Initial divisor
  499.  
  500. BDIVLP1:    DIV    CX            ;AX DX:AX/CX, DX is remainder
  501.         CMP    CX,10000        ;If first division, make 2 dig
  502.         JNZ    DDD1            ;Not first...
  503.  
  504.         MOV    AH,30H            ;Set first digit to 0
  505.         CMP    AL,10            ;2nd digit >9?
  506.         JB    NOAH            ;No
  507.  
  508.         MOV    AH,31H            ;First digit=1
  509.         SUB    AL,10            ;2nd digit is AL-10
  510.  
  511. NOAH:        MOV    [BX],AH            ;Place first digit
  512.         INC    BX            ;Position to second
  513.  
  514. DDD1:        ADD    AL,30H            ;Convert this digit to ASCII
  515.  
  516.         MOV    [BX],AL            ;Place digit in buffer
  517.         INC    BX
  518.  
  519.         MOV    AX,CX            ;Divisor=divisor/10
  520.         PUSH    DX            ;Save old remainder
  521.         MOV    CX,10
  522.         XOR    DX,DX            ;DX:AX is divisor
  523.         DIV    CX
  524.         MOV    CX,AX            ;CX is new divisor
  525.         POP    AX            ;AX is old remainder
  526.  
  527.         CMP    CX,1            ;Divisor=1?
  528.         JNZ    BDIVLP1            ;No, continue
  529.  
  530.         MOV    CX,5            ;Max number of leading zeros
  531.         JMP    LZDROPCOM        ;Go drop any leading zeros
  532. ;---------------
  533. ;
  534. ;    CHECKAOK -- check if all are ok, and if not, set up compare buffer for
  535. ;            comparisons
  536. ;
  537. ;---------------
  538. CHECKAOK:    MOV    DI,5DH            ;Command line filespec
  539.         MOV    CX,11            ;Number of characters to scan
  540.  
  541.         MOV    FILAOK,1        ;Preset value for true
  542.  
  543.         MOV    AX,3F20H        ;Use both ? and space until it
  544.                         ;Is determined what it is
  545.  
  546. CHECKAOK1:    CMP    BYTE PTR [DI],AL    ;Is it the same as last?
  547.         JZ    CHECK1            ;Yes, ok so far
  548.         CMP    BYTE PTR [DI],AH    ;Alternate for ?
  549.         JZ    CHECK1A            ;Yes, ok so far
  550.  
  551.         MOV    FILAOK,0        ;File is not always ok
  552.         RET                ;Done
  553.  
  554. CHECK1:        MOV    AH,AL            ;Copy char, we know what they
  555.                         ;All must be
  556.         INC    DI            ;Point to next char
  557.         LOOP    CHECKAOK1        ;Go for all 11 characters
  558.         RET                ;Done, file always ok
  559.  
  560. CHECK1A:    MOV    AL,AH            ;Copy char, we know what they
  561.         INC    DI            ;All must be. point to next
  562.         LOOP    CHECKAOK1        ;And go for all 11 characters
  563.         RET                ;Done, file always ok
  564. ;---------------
  565. ;
  566. ;    CHECKFIL -- check a file to see if it matches comparison value
  567. ;
  568. ;---------------
  569. CHECKFIL:    MOV    FILOK,1            ;Set to true for now
  570.  
  571.         CMP    FILAOK,1        ;Always ok?
  572.         JNZ    CHECKFIL1        ;No, check this one
  573.         RET                ;Yes, return with this one ok
  574.  
  575. CHECKFIL1:    PUSH    BX            ;Save important regs
  576.         PUSH    CX
  577.         MOV    CX,11            ;File spec length
  578.         MOV    DI,5DH            ;Offset to comparison string
  579. CHECKF2:    MOV    AL,[DI]            ;Get first char to compare
  580.         CMP    AL,'?'            ;Wildcard?
  581.         JZ    CHECKN            ;Yes, this character always ok
  582.         CMP    AL,[BX]            ;No, check with current value
  583.         JZ    CHECKN            ;Yes, ok so far
  584.         POP    CX            ;No, restore registers
  585.         POP    BX
  586.         MOV    FILOK,0            ;File is not ok
  587.         RET                ;Done
  588.  
  589. CHECKN:        INC    BX            ;Point to next character
  590.         INC    DI
  591.         LOOP    CHECKF2            ;Go for all 11 characters
  592.         POP    CX            ;Restore important registers
  593.         POP    BX
  594.         RET                ;Done, file is ok
  595.  
  596. CSEG        ENDS
  597.  
  598.         END    ENTRY
  599. SHAR_EOF
  600. chmod +x 'dirc.asm'
  601. if test -f 'dirc.c'
  602. then
  603.     echo shar: over-writing existing file "'dirc.c'"
  604. fi
  605. cat << \SHAR_EOF > 'dirc.c'
  606. #include <dos.h>
  607. #include <stdlib.h>
  608.  
  609. /*
  610.  |
  611.  |    DIRC.EXE
  612.  |
  613.  |    USAGE:
  614.  |        DIRC [filename[.ext]]<CR>
  615.  |
  616.  |        [filename[.ext]] is used to specify the file(s) whose
  617.  |            directory you want to list.
  618.  |
  619.  |        The information provided includes the free space on the disk.
  620.  |            The freespace is listed both in Granules and Bytes.
  621.  |            The display for each file includes its size in bytes,
  622.  |                the number of granules it occupies, the file
  623.  |                type, and the file mode.
  624.  |
  625.  |        You may use the global characters ? and * in the filename and
  626.  |            extention parameters.
  627.  |
  628.  |        If you do not specify a filename, it defaults to *.*
  629.  |
  630.  |        If you do not specify a filename extention, it defaults to *.
  631.  |
  632.  |    Notes:  Currently sector errors are not dealt with very well, but
  633.  |        then again, I've never seen one.  The funtions do return
  634.  |        error values, but they are not checked.  Also note that
  635.  |        this program was very closely based on my working assembler
  636.  |        from about two years ago, and I just did a quick translation
  637.  |        without doing much careful thought about improvements, of
  638.  |        which there are probably many.
  639.  */
  640.  
  641. #define    DRIVENAME    'A'
  642. #define    DRIVENO        (DRIVENAME-'A')
  643.  
  644. char *typetab[4] = {    /* Types for COCO directory entries */
  645.     "BASIC    ",
  646.     "Data     ",
  647.     "Program  ",
  648.     "Text     "
  649. };
  650. char *asciitab[2] = {    /* File modes for COCO directory entries */
  651.     "Binary",
  652.     "ASCII"
  653. };
  654.  
  655. int fcount, gcount;    /* File/Granule count for dir info */
  656. int filaok, filok;    /* For wildcarding, always ok and this ok */
  657.  
  658. int grans;
  659.  
  660. #define GRANS    68    /* Number of grans on the disk */
  661. #define GSIZE    2304    /* Number of bytes per granule */
  662. #define SECSIZE    256    /* Number of bytes per sector */
  663. #define DIRENT    32    /* Number of bytes per directory entry */
  664.  
  665. int nbsec;        /* Save area for MSDOS value (must restore)*/
  666. char far *thisseg = " ";/* used to find data segment */
  667. char fat[SECSIZE];        /* FAT information buffer from COCO disk */
  668. char dirbuf[SECSIZE];    /* Directory sector buffer from COCO disk */
  669.  
  670. char fbuf[11] =        /* file buffer for comparison to fspec given*/
  671.      "???????????";
  672.  
  673. union REGS inregs;
  674. union REGS outregs;
  675. struct SREGS segregs;
  676.  
  677. main(argc,argv)        /*    main -- Start of DIRC.EXE execution */
  678. int argc;        /* I did not use argc/argv in lieu of DOS's */
  679. char *argv[];        /* PSP for sake of easy wildcard expansions */
  680. {
  681.     char far *(far *vec78h);    /* We need to play with the disk */
  682.     char far *bpsvec;        /* control block area         */
  683.  
  684.     int scnt, ecnt;            /* sector count and entry count     */
  685.     int mode, gran, lbytes, type;
  686.  
  687.     unsigned char *bufp;
  688.  
  689.     checkaok();            /* a little parsing on the PSP     */
  690.  
  691.     printf(" Volume in drive %c is COCO disk\n",DRIVENAME);
  692.     printf(" Directory of COCO disk\n\n");
  693.  
  694.     vec78h = (char far *(far *))(0x78);
  695.                 /* 0000:0078, MSDOS disk info pointer */
  696.     bpsvec = 3 + *vec78h;    /* Get MSDOS bytes per sector ptr */
  697.  
  698.     nbsec = (int) *bpsvec;    /* Save byte for restore later */
  699.     *bpsvec = (char) 1;    /* Set byte to 1 (256 bytes/sector) */
  700.  
  701.     fcount = 0;        /* initialize */
  702.     grans = GRANS;        /* will be used to count down available */
  703.  
  704.     cread(17,2,fat,1);    /* Read coco sector, track 17 sec 2 */
  705.  
  706.     for(scnt=0;scnt<9;scnt++) {    /* Main loop for directory read */
  707.  
  708.         cread(17,scnt+3,dirbuf,1);    /* Read directory sectors    */
  709.  
  710.         bufp = dirbuf;
  711.  
  712.         for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
  713.                         /* entries per sector = 8 */
  714.                         /* ...for each file entry: */
  715.         if (*bufp) {
  716.             checkfil(bufp);        /* Check if it's ok to list */
  717.                         /* result: filok=1, yes */
  718.             if (filok) {
  719.             fcount++;        /* count it, and print name */
  720.             printf("%.8s %.3s    ",bufp,(char *) bufp+8);
  721.             }
  722.  
  723.             mode = (int) *(bufp+12);
  724.             gran = (int) *(bufp+13);
  725.             lbytes = ( (256 * (int)(*(bufp+14))) +
  726.                  (int)(*(bufp+15)) );/* Count is in 6809 format */
  727.                          /* high, then low byte     */
  728.             type = (int) *(bufp+11);
  729.             calcdisp(mode,gran,lbytes,type);
  730.  
  731.             if (filok) {
  732.             printf("%s",typetab[type]);
  733.             if (mode!=0) mode=1;    /* now simply ascii or not */
  734.             printf("%s\n",asciitab[mode]);
  735.             }
  736.         }
  737.         bufp += DIRENT;
  738.         }
  739.     }
  740.     printf("   %5d File(s)%5d Grans, %6ld Bytes free\n",
  741.         fcount, grans,(long) grans*GSIZE);
  742.  
  743.     *bpsvec = (char) nbsec;    /* Set byte to MSDOS value */
  744. }
  745.  
  746. /* calcdisp -- calculate file size, and display if necessary */
  747.  
  748. calcdisp(mode,gran,lbytes,type)
  749. int mode,gran,lbytes,type;
  750. {
  751.     int bytecnt;
  752.  
  753.     gcount = 0;
  754.     bytecnt = lbytes;
  755.  
  756.     do {
  757.         grans--;            /* one less granule avail  */
  758.         gcount++;            /* one more allocated here */
  759.         gran = (int) *(fat+gran);    /* point to next granule   */
  760.         if (gran & 0x80) {        /* if high bit set, last   */
  761.             gran = (gran & 0x3f)-1;    /* find remaining sectors  */
  762.             if (gran>0) bytecnt += gran*SECSIZE;
  763.             break;            /* done               */
  764.         }
  765.         bytecnt += GSIZE;        /* add gran length       */
  766.     } while (gran>=0);            /* we'll actually break    */
  767.     if (filok) printf("%5d%5d  ",bytecnt,gcount); /* print if needed   */
  768. }
  769.  
  770.  
  771. /* check if all are ok, and if not, set up compare buffer for comparisons */
  772. checkaok()
  773. {
  774.     char far *pspfspec;
  775.     int cnt;
  776.     char chk1;
  777.     char *nbuf;
  778.  
  779.     FP_SEG(pspfspec) = _psp;        /* Use the PSP, dos is nice */
  780.     FP_OFF(pspfspec) = 0x5d;        /* to us on wildcards        */
  781.  
  782.     chk1 = *pspfspec;            /* get first character        */
  783.     nbuf=fbuf;
  784.  
  785.     if (chk1==' ' || chk1=='?') {
  786.         filaok=1;            /* if all blank or all '?'  */
  787.         for(cnt=0;cnt<11;cnt++) {
  788.             *nbuf = *pspfspec++;
  789.             if (*nbuf++!=chk1) filaok = 0;
  790.         }                /* if filaok then ALL files */
  791.     } else filaok=0;
  792. }
  793.  
  794. /*    checkfil -- check a file to see if it matches comparison value */
  795. checkfil(nbuf)
  796. char *nbuf;
  797. {
  798.     int cnt;
  799.     filok = 1;
  800.     if (filaok) return;
  801.  
  802.     for (cnt=0;cnt<11;cnt++)
  803.         if ((*(fbuf+cnt) != '?') &&
  804.             (*(fbuf+cnt) != *(nbuf+cnt))) filok=0;
  805.     return;
  806. }
  807.  
  808. int cread(trk,sec,buf,cnt)
  809. int trk,sec;
  810. char *buf;
  811. int cnt;
  812. {
  813.     int errcnt;
  814.     char *temp;
  815.  
  816.     errcnt = 0;
  817.     for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0; /* zero buff */
  818.     if (trk>39 || sec>18) return(-1);    /* don't read bad ptr's */
  819.  
  820.     while (errcnt<4) {
  821.         inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
  822.         inregs.x.bx = (int) buf;    /* pointer to buffer */
  823.         inregs.x.cx = (int) (trk & 0xff)*256
  824.                    +(sec & 0xff);/* Track , Sector */
  825.         inregs.x.dx = DRIVENO;        /* Drive select byte */
  826.         segregs.ds = FP_SEG(thisseg);
  827.         segregs.es = FP_SEG(thisseg);
  828.  
  829.         int86x(0x13,&inregs,&outregs,&segregs);
  830.         if (outregs.x.cflag==0) break;
  831.         creset();
  832.         errcnt++;
  833.     }
  834.     return(errcnt);
  835. }
  836.  
  837. int creset()
  838. {
  839.     inregs.x.ax = 0x0000;        /* 2 = read function, Count=cnt */
  840.     inregs.x.dx = DRIVENO;        /* Drive select byte */
  841.     segregs.ds = FP_SEG(thisseg);
  842.     segregs.es = FP_SEG(thisseg);
  843.  
  844.     int86x(0x13,&inregs,&outregs,&segregs);
  845.     return(outregs.x.cflag);
  846. }
  847. SHAR_EOF
  848. chmod +x 'dirc.c'
  849. if test -f 'fromc.c'
  850. then
  851.     echo shar: over-writing existing file "'fromc.c'"
  852. fi
  853. cat << \SHAR_EOF > 'fromc.c'
  854. #include <dos.h>
  855. #include <stdlib.h>
  856. #include <stdio.h>
  857. #include <fcntl.h>
  858.  
  859. /*
  860.  |
  861.  |    FROMC.EXE
  862.  |
  863.  |    USAGE:
  864.  |        FROMC [filename[.ext]]<CR>
  865.  |
  866.  |        [filename[.ext]] is used to specify the file(s) which
  867.  |            you want to get from COCO disks.
  868.  |
  869.  |        This function also has the side effect of giving you
  870.  |            directory information as it copies (an added
  871.  |            benefit).
  872.  |
  873.  |        The information provided includes the free space on the disk.
  874.  |            The freespace is listed both in Granules and Bytes.
  875.  |            The display for each file includes its size in bytes,
  876.  |                the number of granules it occupies, the file
  877.  |                type, and the file mode.
  878.  |
  879.  |        You may use the global characters ? and * in the filename and
  880.  |            extention parameters.
  881.  |
  882.  |        If you do not specify a filename, it defaults to *.*
  883.  |
  884.  |        If you do not specify a filename extention, it defaults to *.
  885.  |
  886.  */
  887.  
  888. #define    DRIVENAME    'A'
  889. #define    DRIVENO        (DRIVENAME-'A')
  890.  
  891. char *typetab[4] = {    /* Types for COCO directory entries */
  892.     "BASIC    ",
  893.     "Data     ",
  894.     "Program  ",
  895.     "Text     "
  896. };
  897. char *asciitab[2] = {    /* File modes for COCO directory entries */
  898.     "Binary",
  899.     "ASCII"
  900. };
  901.  
  902. int fcount, gcount;    /* File/Granule count for dir info */
  903. int filaok, filok;    /* For wildcarding, always ok and this ok */
  904.  
  905. int grans;
  906.  
  907. #define GRANS    68    /* Number of grans on the disk */
  908. #define GSIZE    2304    /* Number of bytes per granule */
  909. #define SECSIZE    256    /* Number of bytes per sector */
  910. #define DIRENT    32    /* Number of bytes per directory entry */
  911.  
  912. int lastsec;
  913. FILE *filptr;
  914. char *fname = "            \r";
  915.  
  916. int nbsec;        /* Save area for MSDOS value (must restore)*/
  917. char far *thisseg = " ";/* used to find data segment */
  918. char fat[SECSIZE];        /* FAT information buffer from COCO disk */
  919. char dirbuf[SECSIZE];    /* Directory sector buffer from COCO disk */
  920.  
  921. char fbuf[11] =        /* file buffer for comparison to fspec given*/
  922.      "???????????";
  923.  
  924. char inbuff[GSIZE];    /* Input buffer for granules */
  925.  
  926. union REGS inregs;
  927. union REGS outregs;
  928. struct SREGS segregs;
  929.  
  930. main(argc,argv)        /*    main -- Start of DIRC.EXE execution */
  931. int argc;
  932. char *argv[];
  933. {
  934.     char far *(far *vec78h);
  935.     char far *bpsvec;
  936.  
  937.     int scnt, ecnt;
  938.     int mode, gran, lbytes, type;
  939.  
  940.     unsigned char *bufp;
  941.  
  942.     checkaok();
  943.  
  944.     printf(" Volume in drive %c is COCO disk\n",DRIVENAME);
  945.     printf(" Copying files from COCO disk\n\n");
  946.  
  947.     vec78h = (char far *(far *))(0x78);
  948.                 /* 0000:0078, MSDOS disk info pointer */
  949.     bpsvec = 3 + *vec78h;    /* Get MSDOS bytes per sector ptr */
  950.  
  951.     nbsec = (int) *bpsvec;    /* Save byte for restore later */
  952.     *bpsvec = (char) 1;    /* Set byte to 1 (256 bytes/sector) */
  953.  
  954.     fcount = 0;        /* initialize */
  955.     grans = GRANS;
  956.  
  957.     cread(17,2,fat,1);
  958.  
  959.     for(scnt=0;scnt<9;scnt++) {    /* Main loop for directory read */
  960.  
  961.         cread(17,scnt+3,dirbuf,1);
  962.  
  963.         bufp = dirbuf;
  964.  
  965.         for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
  966.                         /* entries per sector = 8 */
  967.                         /* ...for each file entry: */
  968.         if (*bufp) {
  969.             checkfil(bufp);        /* Check if it's ok to list */
  970.                         /* result: filok=1, yes */
  971.             if (filok) {
  972.             fcount++;        /* count it, and print name */
  973.             printf("Copying %.8s %.3s    ",bufp,(char *) bufp+8);
  974.             }
  975.  
  976.             mode = (int) *(bufp+12);
  977.             gran = (int) *(bufp+13);
  978.             lbytes = ( (256 * (int)(*(bufp+14))) +
  979.                  (int)(*(bufp+15)) );/* Count is in 6809 format */
  980.                          /* high, then low byte */
  981.             type = (int) *(bufp+11);
  982.             calcdisp(mode,gran,lbytes,type,bufp);
  983.  
  984.             if (filok) {
  985.             printf("%s",typetab[type]);
  986.             if (mode!=0) mode=1;    /* now simply ascii or not */
  987.             printf("%s\n",asciitab[mode]);
  988.             }
  989.         }
  990.         bufp += DIRENT;
  991.         }
  992.     }
  993.     printf("Done:     %5d File(s) copied\n",fcount);
  994.  
  995.     *bpsvec = (char) nbsec;    /* Set byte to MSDOS value */
  996. }
  997.  
  998. /* calcdisp -- calculate file size, and display if necessary */
  999.  
  1000. calcdisp(mode,gran,lbytes,type,name)
  1001. int mode,gran,lbytes,type;
  1002. char *name;
  1003. {
  1004.     int bytecnt,tgran;
  1005.  
  1006.     gcount = 0;
  1007.     bytecnt = lbytes;
  1008.  
  1009.     if (filok) openfile(name);
  1010.  
  1011.     lastsec = lbytes;
  1012.  
  1013.     do {
  1014.         tgran = gran;
  1015.         grans--;
  1016.         gcount++;
  1017.         gran = (int) *(fat+gran);
  1018.         if (gran & 0x80) {
  1019.             if (filok) copylast(tgran,gran & 0x3f);
  1020.             gran = (gran & 0x3f)-1;
  1021.             if (gran>0) bytecnt += gran*SECSIZE;
  1022.             gran=-1;
  1023.             break;
  1024.         }
  1025.         if (filok) copygran(tgran);
  1026.         bytecnt += (int) GSIZE;
  1027.     } while (gran>=0);
  1028.     if (filok) printf("%5d%5d  ",bytecnt,gcount);
  1029. }
  1030.  
  1031.  
  1032. /* check if all are ok, and if not, set up compare buffer for comparisons */
  1033. checkaok()
  1034. {
  1035.     char far *pspfspec;
  1036.     int cnt;
  1037.     char chk1;
  1038.     char *nbuf;
  1039.  
  1040.     FP_SEG(pspfspec) = _psp;
  1041.     FP_OFF(pspfspec) = 0x5d;
  1042.  
  1043.     chk1 = *pspfspec;
  1044.     nbuf=fbuf;
  1045.  
  1046.     if (chk1==' ' || chk1=='?') filaok=1; else filaok=0;
  1047.  
  1048.     for(cnt=0;cnt<11;cnt++) {
  1049.         *nbuf = *pspfspec++;
  1050.         if (*nbuf++!=chk1) filaok = 0;
  1051.     }
  1052. }
  1053.  
  1054. /*    CHECKFIL -- check a file to see if it matches comparison value */
  1055. checkfil(nbuf)
  1056. char *nbuf;
  1057. {
  1058.     int cnt;
  1059.     filok = 1;
  1060.     if (filaok) return;
  1061.  
  1062.     for (cnt=0;cnt<11;cnt++)
  1063.         if ((*(fbuf+cnt) != '?') &&
  1064.             (*(fbuf+cnt) != *(nbuf+cnt))) filok=0;
  1065.     return;
  1066. }
  1067.  
  1068. openfile(name)
  1069. char *name;
  1070. {
  1071.     int cnt;
  1072.     char *fptr;
  1073.  
  1074.     fptr = fname;
  1075.  
  1076.     for(cnt=0;cnt<8;cnt++) *fptr++ = *(name+cnt);
  1077.     while (*(fptr-1)==' ' && fptr>fname) fptr--;
  1078.     *fptr++ = '.';
  1079.     for(cnt=8;cnt<11;cnt++) *fptr++ = *(name+cnt);
  1080.     while ((*(fptr-1)==' ' || *(fptr-1)=='.') && fptr>fname) fptr--;
  1081.     *fptr = 0;
  1082.  
  1083.     filptr = fopen(fname,"w+b");
  1084. }
  1085.  
  1086. copygran(gran)
  1087. int gran;
  1088. {
  1089.     int secstart;
  1090.  
  1091.     if (gran>=34) gran += 2;
  1092.     secstart = (gran & 1)*9+1;
  1093.     gran /= 2;
  1094.  
  1095.     cread(gran,secstart,inbuff,9);
  1096.  
  1097.     fwrite(inbuff,GSIZE,1,filptr);
  1098. }
  1099.  
  1100. copylast(gran,nsec)
  1101. int gran,nsec;
  1102. {
  1103.     int secstart;
  1104.  
  1105.     if (gran>=34) gran+=2;
  1106.     secstart = (gran & 1)*9+1;
  1107.     gran /= 2;
  1108.  
  1109.     cread(gran,secstart,inbuff,9);
  1110.  
  1111.     nsec -= 1;
  1112.     if (nsec<0) nsec=0;
  1113.  
  1114.     fwrite(inbuff,SECSIZE*nsec+lastsec,1,filptr);
  1115.  
  1116.     fclose(filptr);
  1117. }
  1118.  
  1119. int cread(trk,sec,buf,cnt)
  1120. int trk,sec;
  1121. char *buf;
  1122. int cnt;
  1123. {
  1124.     int errcnt;
  1125.     char *temp;
  1126.  
  1127.     errcnt = 0;
  1128.     for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0;
  1129.     if (trk>39 || sec>18) return(-1);
  1130.  
  1131.     while (errcnt<4) {
  1132.         inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
  1133.         inregs.x.bx = (int) buf;    /* pointer to buffer */
  1134.         inregs.x.cx = (int) (trk & 0xff)*256
  1135.                    +(sec & 0xff);/* Track , Sector */
  1136.         inregs.x.dx = DRIVENO;        /* Drive select byte */
  1137.         segregs.ds = FP_SEG(thisseg);
  1138.         segregs.es = FP_SEG(thisseg);
  1139.  
  1140.         int86x(0x13,&inregs,&outregs,&segregs);
  1141.         if (outregs.x.cflag==0) break;
  1142.         creset();
  1143.         errcnt++;
  1144.     }
  1145.     return(errcnt);
  1146. }
  1147.  
  1148. int creset()
  1149. {
  1150.     inregs.x.ax = 0x0000;        /* 2 = read function, Count=cnt */
  1151.     inregs.x.dx = DRIVENO;        /* Drive select byte */
  1152.     segregs.ds = FP_SEG(thisseg);
  1153.     segregs.es = FP_SEG(thisseg);
  1154.  
  1155.     int86x(0x13,&inregs,&outregs,&segregs);
  1156.     return(outregs.x.cflag);
  1157. }
  1158. SHAR_EOF
  1159. chmod +x 'fromc.c'
  1160. if test -f 'toc.c'
  1161. then
  1162.     echo shar: over-writing existing file "'toc.c'"
  1163. fi
  1164. cat << \SHAR_EOF > 'toc.c'
  1165. #include <dos.h>
  1166. #include <stdlib.h>
  1167. #include <stdio.h>
  1168. #include <fcntl.h>
  1169. #include <io.h>
  1170.  
  1171. /*
  1172.  |
  1173.  |    TOC.EXE
  1174.  |
  1175.  |    USAGE:
  1176.  |        TOC filename.ext {BDPT} {AB}<CR>
  1177.  |
  1178.  |        filename.ext is used to specify the file which you want
  1179.  |            to transfer.  NO wildcards are supported, and you
  1180.  |            MUST include a file type and mode.
  1181.  |
  1182.  |        This is a derivitive of DIRC.C (can you tell?)
  1183.  */
  1184.  
  1185. #define    DRIVENAME    'A'
  1186. #define    DRIVENO        (DRIVENAME-'A')
  1187.  
  1188. char *typetab[4] = {    /* Types for COCO directory entries */
  1189.     "BASIC    ",
  1190.     "Data     ",
  1191.     "Program  ",
  1192.     "Text     "
  1193. };
  1194. char *asciitab[2] = {    /* File modes for COCO directory entries */
  1195.     "Binary",
  1196.     "ASCII"
  1197. };
  1198.  
  1199. int fcount, gcount;    /* File/Granule count for dir info */
  1200. int filaok, filok;    /* For wildcarding, always ok and this ok */
  1201.  
  1202. int grans;
  1203.  
  1204. #define GRANS    68    /* Number of grans on the disk */
  1205. #define GSIZE    2304    /* Number of bytes per granule */
  1206. #define SECSIZE    256    /* Number of bytes per sector */
  1207. #define DIRENT    32    /* Number of bytes per directory entry */
  1208.  
  1209. int lastsec;
  1210. FILE *filptr;
  1211. char *fname = "            \r";
  1212.  
  1213. int nbsec;        /* Save area for MSDOS value (must restore)*/
  1214. char far *thisseg = " ";/* used to find data segment */
  1215. char fat[SECSIZE];        /* FAT information buffer from COCO disk */
  1216. char dirbuf[SECSIZE];    /* Directory sector buffer from COCO disk */
  1217.  
  1218. char fbuf[11] =        /* file buffer for comparison to fspec given*/
  1219.      "???????????";
  1220.  
  1221. char inbuff[GSIZE];    /* Input buffer for granules */
  1222.  
  1223. union REGS inregs;
  1224. union REGS outregs;
  1225. struct SREGS segregs;
  1226.  
  1227. unsigned long int numb;
  1228. unsigned int numg,numrs,numrb;
  1229.  
  1230. main(argc,argv)        /*    main -- Start of DIRC.EXE execution */
  1231. int argc;
  1232. char *argv[];
  1233. {
  1234.     char far *(far *vec78h);
  1235.     char far *bpsvec;
  1236.  
  1237.     int scnt, ecnt, cnt, lcnt;
  1238.     unsigned int mode, gran, lbytes, type;
  1239.  
  1240.     unsigned char *bufp;
  1241.  
  1242.     if (argc!=4) {
  1243.         printf("Usage:   toc (fspec) {BDPT} {AB}\n");
  1244.         exit(1);
  1245.     }
  1246.     switch (*argv[2]) {
  1247.         case 'b':
  1248.         case 'B': {
  1249.             type = 0;
  1250.             break;
  1251.         }
  1252.         case 'd':
  1253.         case 'D': {
  1254.             type = 1;
  1255.             break;
  1256.         }
  1257.         case 'p':
  1258.         case 'P': {
  1259.             type = 2;
  1260.             break;
  1261.         }
  1262.         case 't':
  1263.         case 'T': {
  1264.             type = 3;
  1265.             break;
  1266.         }
  1267.         default: {
  1268.             printf("Bad parameter: %c\n",*argv[2]);
  1269.             exit(1);
  1270.         }
  1271.     }
  1272.     switch (*argv[3]) {
  1273.         case 'a':
  1274.         case 'A': {
  1275.             mode = 1;
  1276.             break;
  1277.         }
  1278.         case 'b':
  1279.         case 'B': {
  1280.             mode = 0;
  1281.             break;
  1282.         }
  1283.         default: {
  1284.             printf("Bad parameter: %c\n",*argv[3]);
  1285.             exit(1);
  1286.         }
  1287.     }
  1288.     checkaok();
  1289.     openfile(fbuf);
  1290.     numb = filelength(fileno(filptr));
  1291.     numg = (int) (numb/GSIZE)+1;
  1292.     numrb = numb - (numg-1)*GSIZE;
  1293.     numrs = (int) (numrb/SECSIZE)+1;
  1294.     numrb -= (numrs-1)*SECSIZE;
  1295.  
  1296.     printf(" Copying %s to COCO disk in drive %c\n",fname,DRIVENAME);
  1297.     printf("    Type = %s",typetab[type]);
  1298.     printf("    Mode = %s",asciitab[mode]);
  1299.     printf("    %d Grans\n\n",numg);
  1300.     vec78h = (char far *(far *))(0x78);
  1301.                 /* 0000:0078, MSDOS disk info pointer */
  1302.     bpsvec = 3 + *vec78h;    /* Get MSDOS bytes per sector ptr */
  1303.  
  1304.     nbsec = (int) *bpsvec;    /* Save byte for restore later */
  1305.     *bpsvec = (char) 1;    /* Set byte to 1 (256 bytes/sector) */
  1306.  
  1307.     fcount = 0;        /* initialize */
  1308.     grans = GRANS;
  1309.  
  1310.     cread(17,2,fat,1);
  1311.  
  1312.     for(cnt=0;cnt<GRANS;cnt++)
  1313.         if (*(fat+cnt)!=(char) 0xff) grans--;
  1314.  
  1315.     if (grans<numg) {
  1316.         printf(" Not enough space:  Only %d grans free\n\n",grans);
  1317.     } else {
  1318.         for(scnt=0;scnt<9;scnt++) {    /* Main loop for directory read */
  1319.         cread(17,scnt+3,dirbuf,1);
  1320.         bufp = dirbuf;
  1321.         for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
  1322.             if (*bufp==0) *bufp=0xff; else bufp+=DIRENT;
  1323.         }
  1324.         if (*bufp==0xff) break;
  1325.         }
  1326.         if (*bufp!=0xff) {
  1327.         printf("No more directory entries left.\n\n");
  1328.         exit(1);
  1329.         }
  1330.         lcnt = -1;
  1331.         for(cnt=0;cnt<11;cnt++) *(bufp+cnt) = *(fbuf+cnt);
  1332.         for(cnt=11;cnt<DIRENT;cnt++) *(bufp+cnt) = (char) 0;
  1333.         *(bufp+11) = (char) type;
  1334.         *(bufp+12) = (char) mode*0xff;
  1335.         *(bufp+15) = (char) numrb;
  1336.         for(cnt=0;cnt<GRANS;cnt++)
  1337.         if (*(fat+cnt)==(char) 0xff) {
  1338.             if (lcnt<0) *(bufp+13)=(char) cnt;
  1339.                 else    *(fat+lcnt)=(char) cnt;
  1340.             lcnt=cnt;
  1341.             if (numg > 1) {
  1342.             copygran(cnt);
  1343.             } else {
  1344.             copylast(cnt,numrs);
  1345.             break;
  1346.             }
  1347.             numg--;
  1348.         }
  1349.         *(fat+cnt)=(char) 0xc0+numrs;
  1350.         cwrite(17,scnt+3,dirbuf,1);
  1351.         cwrite(17,2,fat,1);
  1352.         fclose(filptr);
  1353.     }
  1354.     *bpsvec = (char) nbsec;    /* Set byte to MSDOS value */
  1355. }
  1356.  
  1357. /* check if all are ok, and if not, set up compare buffer for comparisons */
  1358. checkaok()
  1359. {
  1360.     char far *pspfspec;
  1361.     int cnt;
  1362.     char *nbuf;
  1363.  
  1364.     FP_SEG(pspfspec) = _psp;
  1365.     FP_OFF(pspfspec) = 0x5d;
  1366.  
  1367.     filok = 0;
  1368.     filaok = 1;
  1369.     nbuf=fbuf;
  1370.  
  1371.     for(cnt=0;cnt<11;cnt++) {
  1372.         *nbuf = *pspfspec++;
  1373.         if (*nbuf!=' ') filok = 1;
  1374.         if (*nbuf++=='?') filaok = 0;
  1375.     }
  1376.     if (filaok==0) {
  1377.         printf("Wildcards not currently supported\n");
  1378.         exit(1);
  1379.     }
  1380.     if (filok==0) {
  1381.         printf("No file name given\n");
  1382.         exit(1);
  1383.     }
  1384. }
  1385.  
  1386. int cwrite(trk,sec,buf,cnt)
  1387. int trk,sec;
  1388. char *buf;
  1389. int cnt;
  1390. {
  1391.     int errcnt,seccnt;
  1392.     if (trk>39 || sec>18) return(-1);
  1393.  
  1394.     for(seccnt=0;seccnt<cnt;seccnt++) {
  1395.         errcnt = 0;
  1396.  
  1397.         while (errcnt<4) {
  1398.         inregs.x.ax = 0x0301;        /* 3 = write, Count=cnt */
  1399.         inregs.x.bx = (int) buf+SECSIZE*seccnt;
  1400.                         /* pointer to buffer */
  1401.         inregs.x.cx = (int) (trk & 0xff)*256
  1402.                    +((sec+seccnt) & 0xff);
  1403.                         /* Track , Sector */
  1404.         inregs.x.dx = DRIVENO;        /* Drive select byte */
  1405.         segregs.ds = FP_SEG(thisseg);
  1406.         segregs.es = FP_SEG(thisseg);
  1407.  
  1408.         int86x(0x13,&inregs,&outregs,&segregs);
  1409.         if (outregs.x.cflag==0) break;
  1410.         creset();
  1411.         errcnt++;
  1412.         }
  1413.         if (errcnt==4)
  1414.         printf(" Error writing track %d sector %d\n",trk,sec+seccnt);
  1415.     }
  1416.     return(0);
  1417. }
  1418.  
  1419. int cread(trk,sec,buf,cnt)
  1420. int trk,sec;
  1421. char *buf;
  1422. int cnt;
  1423. {
  1424.     int errcnt;
  1425.     char *temp;
  1426.  
  1427.     errcnt = 0;
  1428.     for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0; /* zero buff */
  1429.     if (trk>39 || sec>18) return(-1);
  1430.  
  1431.     while (errcnt<4) {
  1432.         inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
  1433.         inregs.x.bx = (int) buf;    /* pointer to buffer */
  1434.         inregs.x.cx = (int) (trk & 0xff)*256
  1435.                    +(sec & 0xff);/* Track , Sector */
  1436.         inregs.x.dx = DRIVENO;        /* Drive select byte */
  1437.         segregs.ds = FP_SEG(thisseg);
  1438.         segregs.es = FP_SEG(thisseg);
  1439.  
  1440.         int86x(0x13,&inregs,&outregs,&segregs);
  1441.         if (outregs.x.cflag==0) break;
  1442.         creset();
  1443.         errcnt++;
  1444.     }
  1445.     return(errcnt);
  1446. }
  1447.  
  1448. int creset()
  1449. {
  1450.     inregs.x.ax = 0x0000;        /* 2 = read function, Count=cnt */
  1451.     inregs.x.dx = DRIVENO;        /* Drive select byte */
  1452.     segregs.ds = FP_SEG(thisseg);
  1453.     segregs.es = FP_SEG(thisseg);
  1454.  
  1455.     int86x(0x13,&inregs,&outregs,&segregs);
  1456.     return(outregs.x.cflag);
  1457. }
  1458.  
  1459. openfile(name)
  1460. char *name;
  1461. {
  1462.     int cnt;
  1463.     char *fptr;
  1464.  
  1465.     fptr = fname;
  1466.  
  1467.     for(cnt=0;cnt<8;cnt++) *fptr++ = *(name+cnt);    /* parse filename */
  1468.     while (*(fptr-1)==' ' && fptr>fname) fptr--;
  1469.     *fptr++ = '.';                    /* put in '.'      */
  1470.     for(cnt=8;cnt<11;cnt++) *fptr++ = *(name+cnt);
  1471.     while ((*(fptr-1)==' ' || *(fptr-1)=='.') && fptr>fname) fptr--;
  1472.     *fptr = 0;
  1473.  
  1474.     if ((filptr = fopen(fname,"rb"))==NULL) {
  1475.         printf("File not found\n");
  1476.         exit(1);
  1477.     }
  1478. }
  1479.  
  1480. copygran(gran)
  1481. int gran;
  1482. {
  1483.     int secstart;
  1484.  
  1485.     if (gran>=34) gran += 2;        /* adjust around directory */
  1486.     secstart = (gran & 1)*9+1;        /* Find start sector       */
  1487.     gran /= 2;                /* Now is track pointer       */
  1488.     fread(inbuff,GSIZE,1,filptr);        /* read in file from DOS   */
  1489.     cwrite(gran,secstart,inbuff,9);        /* write out file to coco  */
  1490.     cwrite(gran,secstart,inbuff,9);        /* I did have some write   */
  1491.                         /* errors and this does       */
  1492.                         /* cure them, probably the */
  1493.                         /* lack of delay on first  */
  1494.                         /* write causes a problem  */
  1495.                         /* anyone else?           */
  1496. }
  1497.  
  1498. copylast(gran,nsec)
  1499. int gran,nsec;
  1500. {
  1501.     int secstart;
  1502.  
  1503.     if (gran>=34) gran+=2;            /* skip directory */
  1504.     secstart = (gran & 1)*9+1;        /* find sector      */
  1505.     gran /= 2;                /* find track      */
  1506.  
  1507.     fread(inbuff,GSIZE,1,filptr);        /* read source      */
  1508.  
  1509.     cwrite(gran,secstart,inbuff,9);        /* write destination */
  1510. }
  1511. SHAR_EOF
  1512. chmod +x 'toc.c'
  1513. #    End of shell archive
  1514. exit 0
  1515.